﻿using System;
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using DG.Common.Patterns.Commands;
using DG.Common.Patterns.MVVM;
using TCC.ControleFluxoDeCaixa.Apresentacao.ViewModels.Credito;
using TCC.ControleFluxoDeCaixa.Apresentacao.Views;
using TCC.ControleFluxoDeCaixa.Model.Contas;
using TCC.ControleFluxoDeCaixa.Model.Entities;
using TCC.ControleFluxoDeCaixa.Model.Fluxo;
using TCC.ControleFluxoDeCaixa.Model.Fluxo.Credito;

namespace TCC.ControleFluxoDeCaixa.Apresentacao.ViewModels
{
    public class BuscarLancamentoWindowViewModel : ViewModelBase
    {
        private ContaFinanceira _conta;
        private Categoria _categoria;
        private DateTime? _dataInicio;
        private readonly FluxoDeCaixaContextFiltrado _context;
        private DateTime? _dataFim;
        private IEnumerable<Lancamento> _lancamentos;
        private Lancamento _selectedLancamento;
        private string _palavraChave;


        public BuscarLancamentoWindowViewModel(FluxoDeCaixaContextFiltrado context)
        {
            _context = context;
        }

        public ContaFinanceira Conta
        {
            get { return _conta; }
            set
            {
                if (Equals(value, _conta)) return;
                _conta = value;
                OnPropertyChanged("Conta");
            }
        }

        public Categoria Categoria
        {
            get { return _categoria; }
            set
            {
                if (Equals(value, _categoria)) return;
                _categoria = value;
                OnPropertyChanged("Categoria");
            }
        }

        public DateTime? DataInicio
        {
            get { return _dataInicio; }
            set
            {
                if (value.Equals(_dataInicio)) return;
                _dataInicio = value;
                OnPropertyChanged("DataInicio");
            }
        }

        public DateTime? DataFim
        {
            get { return _dataFim; }
            set
            {
                if (value.Equals(_dataFim)) return;
                _dataFim = value;
                OnPropertyChanged("DataFim");
            }
        }

        public IEnumerable<Lancamento> Lancamentos
        {
            get { return _lancamentos; }
            set
            {
                if (Equals(value, _lancamentos)) return;
                _lancamentos = value;
                OnPropertyChanged("Lancamentos");
            }
        }

        public string PalavraChave
        {
            get { return _palavraChave; }
            set
            {
                if (value == _palavraChave) return;
                _palavraChave = value;
                OnPropertyChanged("PalavraChave");
            }
        }

        private void FiltrarLancamentos()
        {
            var categoriaTrans = _context.GetCategoriaTransferencia();
            
            var query = _context.Lancamentos
               .Where(c => c.Categoria.CategoriaId != categoriaTrans.CategoriaId).AsQueryable();

           
            if (!String.IsNullOrWhiteSpace(PalavraChave)) query = query
                .Where(e => e.Nome.ToLower().Contains(PalavraChave.ToLower()) 
                    || e.Categoria.Nome.ToLower().Contains(PalavraChave.ToLower())
                    || e.Movimentos.Any(m => m.Historico.ToLower().Contains(PalavraChave.ToLower()))
                    || e.Movimentos.Any(m => m.Conta.Nome.ToLower().Contains(PalavraChave.ToLower())));
            if (Conta != null)
            {
                query = query.Where(c=> c.Movimentos.Any(m=> m.Conta.ContaFinanceiraId == Conta.ContaFinanceiraId));
            }
            if (Categoria != null) query = query.Where(c => c.Categoria.CategoriaId == Categoria.CategoriaId);
            if (DataFim.HasValue) query = query.Where(c => c.DataDoLancamento <= DataFim);
            if (DataInicio.HasValue) query = query.Where(c => c.DataDoLancamento >= DataInicio);
           
           
            Lancamentos = query.ToArray();
            
            if (!Lancamentos.Any())
            {
                SendMessage("Nenhuma lançamento encontrado");
            }
               
        }

        public Lancamento SelectedLancamento
        {
            get { return _selectedLancamento; }
            set
            {
                if (Equals(value, _selectedLancamento)) return;
                _selectedLancamento = value;
                OnPropertyChanged("SelectedLancamento");
            }
        }

        public ICommand BuscarLancamento
        {
            get { return new FunctionalCommand(FiltrarLancamentos); }
        }
        public ICommand LimparFiltros
        {
            get { return new FunctionalCommand(() =>
            {
                Conta = null;
                Categoria = null;
                DataInicio = null;
                DataFim = null;
                PalavraChave = null;
                Lancamentos = null;
                SelectedLancamento = null;
                SendMessage("Filtros zerados");
            }); }
        }
        public IEnumerable<ContaFinanceira> GetContas
        {
            get { return _context != null ? _context.ContaFinanceiras.ToArray() : null; }
        }
        public IEnumerable<Categoria> GetCategorias
        {
            get { return _context != null ? _context.Categorias.ToArray() : null; }
        }

        public ICommand EditarLancamento
        {
            get
            {
                return new FunctionalCommand((arg) =>
                {
                    var lanc = arg as Lancamento;
                    if (lanc != null)
                    {
                        if (lanc.Movimentos.All(m => m.Conta is ContaCredito))
                        {
                            var vm = new LancamentoCartaoCreditoWindowViewModel();
                            vm.SetAction(FluxoContextFactory.GetInstance().Create(), CRUDOperationType.Update, lanc);
                            var telaLancamentoCartaoCredito = new LancamentoCartaoDeCreditoWindow(vm);
                            telaLancamentoCartaoCredito.Show();
                        }
                        else
                        {
                            LancamentoCadastroWindow.Modificar(lanc, null);
                        }
                    }
                });
            }
        }
    }
}
